from datetime import datetime
from pathlib import Path
from typing import Dict, Union
from .area_codes import AreaCodeManager

class IdCard:
    """身份证号码验证与信息提取类
    
    用于验证中国居民身份证号码的合法性，并提取号码中包含的个人信息。
    支持15位和18位身份证号码。
    """
    
    def __init__(self, id_number: str):
        """初始化身份证对象
        
        Args:
            id_number: 身份证号码(15位或18位)
        """
        self.id = str(id_number).strip()
        self._area_manager = AreaCodeManager()
        if not self.validate:
            raise ValueError(f'无效的身份证号码: {self.checkIdcard()[1]}')
            
    def __str__(self) -> str:
        return f"IdCard(number='{self.id}')"
    
    def __repr__(self) -> str:
        return self.__str__()

    @property
    def validate(self) -> bool:
        """验证身份证号码是否合法"""
        return self.checkIdcard()[0]
    
    def checkIdcard(self) -> tuple:
        """检查身份证号码的合法性
        
        Returns:
            tuple: (是否合法, 错误信息)
        """
        id_number = self.id
        
        if not id_number.isdigit() and len(id_number) != 18:
            return False, "身份证号码格式错误"
            
        # 验证地区码
        if not self.get_area(id_number[0:6]):
            return False, "地区编码不存在"
            
        # 验证出生日期
        try:
            birthday = datetime.strptime(id_number[6:14], '%Y%m%d')
            if birthday > datetime.now():
                return False, "出生日期不能大于当前日期"
        except ValueError:
            return False, "出生日期无效"
            
        # 验证校验码
        if len(id_number) == 18:
            factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
            parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
            sum = 0
            for i in range(17):
                sum += int(id_number[i]) * factor[i]
            if parity[sum % 11] != id_number[-1].upper():
                return False, "校验码错误"
                
        return True, "验证通过"

    def get_area(self, code: str) -> str:
        """获取行政区划名称"""
        return self._area_manager.get_area(code)

    @property
    def fullarea(self) -> str:
        """获取完整的行政区划信息"""
        return self._area_manager.get_full_area(self.id[0:6])

    @property
    def sex(self) -> str:
        """获取性别(英文)"""
        return 'female' if int(self.id[16:17]) % 2 == 0 else 'male'
    
    @property
    def sex_cn(self) -> str:
        """获取性别(中文)"""
        return '女' if int(self.id[16:17]) % 2 == 0 else '男'

    @property
    def birthday(self) -> datetime:
        """获取出生日期"""
        return datetime.strptime(self.id[6:14], '%Y%m%d')

    @property
    def age(self) -> int:
        """获取年龄"""
        today = datetime.now()
        born = self.birthday
        age = today.year - born.year
        if (today.month, today.day) < (born.month, born.day):
            age -= 1
        return age

    @property
    def info_to_dict(self) -> Dict[str, Union[str, datetime, int]]:
        """获取身份证包含的所有信息
        
        Returns:
            Dict: 包含身份证所有信息的字典
        """
        return {
            'id': self.id,
            'fullarea': self.fullarea,
            'sex': self.sex,
            'sex_cn': self.sex_cn,
            'birthday': self.birthday,
            'age': self.age
        }



